package kamkor.ann.namerecog.network.trainer

import kamkor.ann.namerecog.network.converter._
import kamkor.ann.namerecog.network.parser._
import java.io.File
import scala.io.Source
import org.encog.neural.data.basic.BasicNeuralDataSet
import org.encog.neural.data.basic.BasicNeuralData

/**
 * Utility class that generates training/test data for neural network
 * 
 * @author kamkor 
 *
 */
class NetworkDataGenerator(networkInputLength: Int,inputConv: InputConverter) {
	
	/** Generates BasicNeuralDataSet from given surnames
	 * If surname is too short, empty inputs are appended to the right of input array
	 * 
	 * @param surnames contains arrays of ie. polish surnames, russian surnames etc.
	 * @return BasicNeuralDataSet - inputs and ideal outputs
	 */
	def generateNetworkData(surnames: Array[Array[String]]): BasicNeuralDataSet = {
		val networkData = new BasicNeuralDataSet()
		
		// iterate each surname group, ie. polish, russian, german etc.
		for (nationality <- 0 until surnames.length) {			
			// create ideal output for given nationality
			val idealOutput = new Array[Double](surnames.length)		
			idealOutput(nationality) = 1											
			
			for (surname <- surnames(nationality)) {			
				val surnameConv = inputConv.convert(surname, networkInputLength)
				networkData.add(new BasicNeuralData(surnameConv), new BasicNeuralData(idealOutput))			
			}
		}
		networkData	
	}	
}

/**
 * Utility object, which contains methods useful for preparing generateNetworkData surnames input
 * 
 * @author kamkor
 *
 */
object NetworkDataGenerator {
	
	/** Splits surnames array as:
	 * firstArray = all surnames as surnames(i + step), 
	 * where i = startIndex, startIndex + 1, surnames.length - 1
	 * 
	 * secondArray = difference beetwen surnames and firstArray  
	 * 
	 * @param surnames ie. Array("Korzekwa", "Momot", "Gates")
	 * @param startIndex surnames before this index are ignored
	 * @param step see function description
	 * @return tuple (firstArray, secondArray)
	 */
	def splitSurnames(surnames: Array[String], startIndex: Int, step: Int): (Array[String], Array[String]) = {
		val firstArray = for (i <- startIndex until surnames.length by step) yield surnames(i)
		val secondArray = surnames.diff(firstArray)
		(firstArray.toArray, secondArray)
	}
}